﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FineSoft.Models
{
	public class ComponentObject : ExtObject
	{
		private NativeObject _IdConfig;
		public NativeObject IdConfig
		{
			get
			{
				if (this._IdConfig == null)
				{
					this._IdConfig = (NativeObject)this.Configs["id"];
					if (this._IdConfig == null)
					{
						this._IdConfig = new NativeObject();
						this._IdConfig.Type = Class.String;
						this.Configs["id"] = this._IdConfig;
					}
				}
				return this._IdConfig;
			}
		}

		public string Id
		{
			get
			{
				return (string)((NativeObject)this.IdConfig).Value;
			}
			set
			{
				this.IdConfig.Value = value;
			}
		}

		private bool? _IsContainer;
		public bool IsContainer
		{
			get
			{
				if (this._IsContainer == null)
					this._IsContainer = ((ComponentClass)this.Type).IsContainer;
				return this._IsContainer.Value;
			}
		}

		private System.Collections.Generic.Dictionary<ContainerConfig, System.Collections.Generic.List<ComponentObject>> _Containers;
		public System.Collections.Generic.Dictionary<ContainerConfig, System.Collections.Generic.List<ComponentObject>> Containers
		{
			get
			{
				if (this._Containers == null)
				{
					this._Containers = new Dictionary<ContainerConfig, System.Collections.Generic.List<ComponentObject>>();
					if (this.IsContainer)
						foreach (ContainerConfig config in ((ComponentClass)this.Type).ContainerConfigs)
							this._Containers[config] = new System.Collections.Generic.List<ComponentObject>();
				}
				return this._Containers;
			}
		}

		private System.Collections.Generic.KeyValuePair<ContainerConfig, System.Collections.Generic.List<ComponentObject>>? _SelectedContainer;
		public System.Collections.Generic.KeyValuePair<ContainerConfig, System.Collections.Generic.List<ComponentObject>> SelectedContainer
		{
			get
			{
				if (this.Containers.Count == 0)
					return new KeyValuePair<ContainerConfig, List<ComponentObject>>();
				if (this._SelectedContainer == null)
					this._SelectedContainer = this.Containers.First();
				return this._SelectedContainer.Value;
			}
			set
			{
				this.RaisePropertyChanging("SelectedContainer");
				this._SelectedContainer = value;
				this.RaisePropertyChanged("SelectedContainer");
			}
		}

		private ComponentObject _ParentComponent;
		public ComponentObject ParentComponent
		{
			get
			{
				return this._ParentComponent;
			}
			set
			{
				this._ParentComponent = value;
				this._NearestContainer = null;
			}
		}

		private ComponentObject _NearestContainer;
		public ComponentObject NearestContainer
		{
			get
			{
				if (this._NearestContainer == null)
					if (((ComponentClass)this.Type).IsContainer)
						this._NearestContainer = this;
					else this._NearestContainer = this.ParentComponent;
				return this._NearestContainer;
			}
		}

		public override string ConfigsString
		{
			get
			{
				string configsString = base.ConfigsString;
				configsString = configsString.Substring(0, configsString.Length - 2);
				foreach(ContainerConfig config in this.Containers.Keys)
				{
					System.Collections.Generic.List<ComponentObject> items = this.Containers[config];

					if (items.Count == 0)
						continue;
					//if (configsString.Last() == '{')
						configsString += ",";
					configsString += config.Name + ":[";
					configsString += string.Join(",", items.Select(c => c.ConfigsString).ToArray());
					configsString += "]";
				}
				configsString += "})";
				return "this." + this.Id + "=" + configsString;
			}
		}

		private ComponentObject _RefreshContainer;
		public ComponentObject RefreshContainer
		{
			get
			{
				if (this._RefreshContainer == null)
				{
					if (this.ParentComponent == null)
						this._RefreshContainer = this;
					else for (ComponentObject component = this; component != null; component = component.ParentComponent)
							if (component.ParentComponent == null || component.ParentComponent.Containers[component.ParentComponent.Containers.Keys.First(k => k.Name == "items")].Contains(component))
							{
								this._RefreshContainer = component;
								break;
							}
				}
				return this._RefreshContainer;
			}
		}

		public ComponentObject()
		{
		}

		#region ISerializable 成员

		public ComponentObject(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
			: base(info, context)
		{
			foreach (ContainerConfig config in this.Containers.Keys)
			{
				System.Collections.Generic.List<ComponentObject> components = (System.Collections.Generic.List<ComponentObject>)info.GetValue("Container_" + config.Name, typeof(System.Collections.Generic.List<ComponentObject>));
				foreach (ComponentObject component in components)
					component.ParentComponent = this;
				this.Containers[config] = components;
			}
			this.SelectedContainer = this.Containers.ElementAt(info.GetInt32("SelectedContainer"));
		}

		public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
		{
			foreach (ContainerConfig config in this.Containers.Keys)
				info.AddValue("Container_" + config.Name, this.Containers[config]);
			info.AddValue("SelectedContainer", System.Array.IndexOf(this.Containers.ToArray(), this.SelectedContainer));
		}

		#endregion
	}
}